<template>
  <div class="node-view-data-row">
    <el-input
      v-model="nvValue"
      size="mini"
      :placeholder="placeholder"
      clearable
    />
  </div>
  <el-scrollbar
    class="node-view-data-tree"
    style="height: 400px;">
    <el-tree
      :data="renderDataTree"
      default-expand-all
      class="menu-custom-tree">
      <template #default="{ node, data }">
        <span class="menu-custom-tree-node">
            <div class="menu-custom-label">
                <span
                  v-text="data.label"
                  class="node-prop-title"
                  v-tippy="{ arrow: true }"
                  content="点击复制"
                  v-copy="data.label"
                />
                <span v-if="data.type" class="node-prop-type">（{{ data.type }}）</span>
                <span
                  v-if="data.prop && (data.prop !== data.label)"
                  class="node-prop-code"
                > - {{ data.prop }}</span>
                <span v-text="data.path"></span>
            </div>
            <span
              class="node-prop-btn"
              @click.stop="handleSelectTreePath(data)"
            >选择</span>
        </span>
      </template>
    </el-tree>
  </el-scrollbar>
</template>

<script setup>
import {ref, reactive, computed, watch, onMounted, toRefs} from 'vue'

// 定义 props
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  placeholder: {
    type: String,
    default: '选择/自定义 数据路径'
  },
  nvType: {
    type: String,
    default: ''
  },
  value: {
    type: String,
    default: ''
  },
  item: {
    type: Object,
    default: null
  },
  page: {
    type: Object,
    default: null
  },
  form: {
    type: Object,
    default: null
  },
  dataset: {
    type: Object,
    default: null
  },
  elemNodes: {
    type: [Array, Object],
    default: () => []
  },
  currentEleData: {
    type: Object,
    default: null
  }
})

// 定义 emits
const emit = defineEmits(['change', 'select'])

// 状态
const state = reactive({
  // nvType: "",
  nvValue: '',
  varDataTree: [],
  itemStaticDataTree: [],
  itemVarDataTree: [],
  itemMApiDataTree: [],
  itemFormDataTree: []
})

const {
  nvValue,
  varDataTree,
  itemStaticDataTree,
  itemVarDataTree,
  itemMApiDataTree,
  itemFormDataTree
} = toRefs(state)

// 计算属性
const isApi = computed(() => _.get(props.item, 'data_type') === 'dync')
const isMApi = computed(() => _.get(props.item, 'data_type') === 'microapi')
const isPageVar = computed(() => _.get(props.item, 'data_type') === 'pageVar')
const isStatic = computed(() => _.get(props.item, 'data_type') === 'static')

const renderDataTree = computed(() => {
  if (props.nvType === 'var') {
    return state.varDataTree
  }

  let renderTree = []

  if (isApi.value) {
    renderTree = state.itemFormDataTree
  } else if (isMApi.value) {
    renderTree = state.itemMApiDataTree
  } else if (isPageVar.value) {
    renderTree = state.itemVarDataTree
  } else if (isStatic.value) {
    renderTree = state.itemStaticDataTree
  }

  if (props.nvType === 'scope') {
    // 获取最近的 multiple 节点
    const code = _.get(props.currentEleData, '_code')
    const nodeParents = $utils.getTreePath(code, props.elemNodes, 'code', 'children', true)
    const multiNodes = _.filter(nodeParents, np => isMultipleNode(_.get(np, 'def')))

    if (multiNodes && multiNodes.length) {
      let realRenderTree = renderTree

      for (let i = 0; i < multiNodes.length; i++) {
        const mn = multiNodes[i]
        const value = _.get(mn, 'def._value')
        let nvValue = ''

        if (value) {
          nvValue = value

          if (_.indexOf(value, ':') >= 0) {
            const arrs = _.split(value, ':')
            nvValue = _.get(arrs, '[1]')
          }

          const subTreeNode = $utils.getTreeData(realRenderTree, 'rela', nvValue)

          if (subTreeNode) {
            realRenderTree = [subTreeNode]
          } else {
            realRenderTree = []
            break
          }
        }
      }

      renderTree = realRenderTree
    }
  }

  return renderTree
})

// 生命周期钩子
onMounted(() => {
  init()
})

// Watchers
watch(
  () => props.value,
  (newVal) => {
    state.nvValue = newVal
  }
)

watch(
  () => state.nvValue,
  (val) => {
    emit('change', val)
  }
)

watch(
  () => props.dataset,
  () => {
    init()
  },
  {deep: true}
)

// 方法实现
const init = () => {
  initVarDataTree()
  initItemVarDataTree()
  initItemStaticDataTree()
  initItemMApiDataTree()
  initItemFormDataTree()
}

const schemaToTree = (schema, parent, propName) => {
  const parentId = _.get(parent, 'id') || ''
  const parentRela = _.get(parent, 'rela') || ''
  let id = ''
  let rela = ''

  if (propName === '[0]') {
    id = parentId ? `${parentId}${propName}` : propName
    rela = ''
  } else if (propName) {
    id = parentId ? `${parentId}.${propName}` : propName
    rela = parentRela ? `${parentRela}.${propName}` : propName
  }

  const node = {label: _.get(schema, 'title'), id, rela}

  // 处理类型及其它字段
  switch (schema.type) {
    case 'object':
      node.children = []
      for (const key in schema.properties) {
        const childSchema = schema.properties[key]
        const title = _.get(childSchema, 'title') || ''
        const child = schemaToTree(childSchema, node, key)
        let label = key

        if (title) {
          label = title
        }

        child.label = label
        child.type = _.get(childSchema, 'type')
        child.prop = key
        node.children.push(child)
      }
      // 处理required属性
      if (schema.required && schema.required.length > 0) {
        node.required = schema.required
      }
      break
    case 'array':
      if (!schema.items.type) schema.items.type = 'object'
      const child = schemaToTree(schema.items, node, '[0]')

      child.label = '行记录'
      child.type = _.get(schema.items, 'type')
      child.prop = ''
      node.children = [child]
      node.type = 'array'
      break
    default:
      node.type = schema.type
      break
  }

  return node
}

const getFormSchema = () => {
  const schema = _.cloneDeep(formSchema)
  const formItems = _.get(props.form, 'items') || _.get(props.item, '_form.items')
  const props = {}

  _.each(formItems, fi => {
    const title = _.get(fi, 'label')
    const name = _.get(fi, 'name')
    const itemType = _.get(fi, 'type')
    const multiMode = _.get(fi, 'multi_mode')
    let type = 'string'

    if (_.indexOf(['formdata'], itemType) >= 0) return
    if (_.indexOf(['number', 'slider', 'star'], itemType) >= 0) type = 'number'

    const prop = {
      title,
      type
    }

    if (multiMode === 'Y') {
      prop.type = 'array'
      prop.items = {
        title,
        type
      }
    }

    props[name] = prop
  })

  schema.properties.datas.items.properties = props
  return schema
}

const initVarDataTree = () => {
  let varDataTree = []
  const vars = _.get(props.page, 'vars')
  const varVals = {}

  if (vars && vars.length) {
    for (let i = 0; i < vars.length; i++) {
      const iv = vars[i]
      const prop = _.get(iv, 'prop')
      if (prop) {
        varVals[prop] = _.get(props.dataset, `state.${prop}`)
      }
    }

    const varSchema = $utils.createSchema(varVals)
    const root = schemaToTree(varSchema)

    varDataTree = _.get(root, 'children', [])
  }

  state.varDataTree = varDataTree
}

const initItemVarDataTree = () => {
  let itemVarDataTree = []

  if (isPageVar.value) {
    const varName = _.get(props.item, 'data_dync.pageVar')
    const varData = _.get(props.dataset, `state.${varName}`)

    if (varData) {
      const varSchema = $utils.createSchema(varData)
      const root = schemaToTree(varSchema)
      itemVarDataTree = _.get(root, 'children', [])
    }
  }

  state.itemVarDataTree = itemVarDataTree
}

const initItemStaticDataTree = () => {
  let itemStaticDataTree = []
  const staticSchema = _.get(props.item, 'data_schema')

  if (staticSchema) {
    const root = schemaToTree(staticSchema, null, 'datas')
    itemStaticDataTree = [root]
  }

  state.itemStaticDataTree = itemStaticDataTree
}

const initItemMApiDataTree = () => {
  let itemMApiDataTree = []

  if (isMApi.value) {
    const alias = _.get(props.item, 'alias') || _.get(props.item, 'page_item_code')
    const data = _.cloneDeep(_.get(props.dataset, `items.${alias}`))

    // 忽略接口中 form 的信息
    if (_.get(data, 'form.form_id')) delete data.form

    const schema = $utils.createSchema(data)
    const root = schemaToTree(schema)

    itemMApiDataTree = _.get(root, 'children', [])
  }

  state.itemMApiDataTree = itemMApiDataTree
}

const initItemFormDataTree = () => {
  let itemFormDataTree = []

  if (isApi.value) {
    const schema = getFormSchema()
    const root = schemaToTree(schema)
    itemFormDataTree = _.get(root, 'children', [])
  }

  state.itemFormDataTree = itemFormDataTree
}

const handleSelectTreePath = (data) => {
  let type = _.get(data, 'type')
  let val = ''

  if (props.nvType === 'scope') {
    if (hasForEleNode()) {
      val = _.get(data, 'rela')
    } else {
      val = _.get(data, 'id')

      const datasPathDef = _.get(props.item, 'data_fieldsmap._rowsPath') || 'datas'

      if (val) val = val.replace(new RegExp(`^${datasPathDef}`), '')
    }
  } else {
    val = _.get(data, 'id')
  }

  if (val) state.nvValue = val

  emit('select', val)
}

const hasForEleNode = () => {
  const code = _.get(props.currentEleData, '_code')
  const nodeParents = $utils.getTreePath(code, props.elemNodes, 'code', 'children', true)
  const multiNodes = _.filter(nodeParents, np => isMultipleNode(_.get(np, 'def')))

  return multiNodes && multiNodes.length > 0
}

// 初始数据
const formSchema = {
  title: '属性树',
  type: 'object',
  properties: {
    datas: {
      type: 'array',
      items: {
        type: 'object',
        properties: {}
      }
    },
    page: {
      type: 'object',
      title: '分页信息',
      properties: {
        page: {
          type: 'number',
          title: '页码'
        },
        pageSize: {
          type: 'number',
          title: '每页数'
        },
        total: {
          type: 'number',
          title: '总数据'
        }
      }
    }
  }
}
</script>
